/**
 * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
 */
package com.jeesite.modules.sys.db;

import org.quartz.CronTrigger;
import org.springframework.beans.factory.annotation.Autowired;

import com.jeesite.common.callback.MethodCallback;
import com.jeesite.common.config.Global;
import com.jeesite.common.idgen.IdGen;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.tests.BaseInitDataTests;
import com.jeesite.modules.gen.entity.GenTable;
import com.jeesite.modules.gen.entity.GenTableColumn;
import com.jeesite.modules.gen.service.GenTableService;
import com.jeesite.modules.job.dao.JobDao;
import com.jeesite.modules.job.entity.JobEntity;
import com.jeesite.modules.msg.task.impl.MsgLocalMergePushTask;
import com.jeesite.modules.msg.task.impl.MsgLocalPushTask;
import com.jeesite.modules.sys.dao.RoleMenuDao;
import com.jeesite.modules.sys.entity.Area;
import com.jeesite.modules.sys.entity.Company;
import com.jeesite.modules.sys.entity.CompanyOffice;
import com.jeesite.modules.sys.entity.Config;
import com.jeesite.modules.sys.entity.DictData;
import com.jeesite.modules.sys.entity.DictType;
import com.jeesite.modules.sys.entity.EmpUser;
import com.jeesite.modules.sys.entity.Employee;
import com.jeesite.modules.sys.entity.EmployeePost;
import com.jeesite.modules.sys.entity.Log;
import com.jeesite.modules.sys.entity.Menu;
import com.jeesite.modules.sys.entity.Module;
import com.jeesite.modules.sys.entity.Office;
import com.jeesite.modules.sys.entity.Post;
import com.jeesite.modules.sys.entity.Role;
import com.jeesite.modules.sys.entity.RoleDataScope;
import com.jeesite.modules.sys.entity.RoleMenu;
import com.jeesite.modules.sys.entity.User;
import com.jeesite.modules.sys.entity.UserDataScope;
import com.jeesite.modules.sys.entity.UserRole;
import com.jeesite.modules.sys.service.AreaService;
import com.jeesite.modules.sys.service.CompanyService;
import com.jeesite.modules.sys.service.ConfigService;
import com.jeesite.modules.sys.service.DictDataService;
import com.jeesite.modules.sys.service.DictTypeService;
import com.jeesite.modules.sys.service.EmpUserService;
import com.jeesite.modules.sys.service.MenuService;
import com.jeesite.modules.sys.service.ModuleService;
import com.jeesite.modules.sys.service.OfficeService;
import com.jeesite.modules.sys.service.PostService;
import com.jeesite.modules.sys.service.RoleService;
import com.jeesite.modules.sys.service.UserService;

/**
 * 初始化核心表数据
 *
 * @author ThinkGem
 * @version 2017-10-22
 */
public class InitCoreData extends BaseInitDataTests {

    @Override
    public void begin() {
        super.begin(InitCoreData.class);
    }

    /**
     * 建表语句执行
     */
    public void createTable() throws Exception {
        runScript("core.sql");
        runScript("job.sql");
        runScript("test.sql");
    }

    /**
     * 清理日志表
     */
    public void initLog() throws Exception {
        clearTable(Log.class);
    }

    @Autowired
    private AreaService areaService;

    /**
     * 区域、行政区划表
     */
    public void initArea(String... prefixes) throws Exception {
        clearTable(Area.class);
        initExcelData(Area.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    Area entity = (Area) params[1];
                    entity.setIsNewRecord(true);
                    if (prefixes == null || prefixes.length == 0
                            || StringUtils.startsWithAny(entity.getAreaCode(), prefixes)) {
                        areaService.save(entity);
                    }
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private ConfigService configService;

    /**
     * 参数配置表
     */
    public void initConfig() throws Exception {
        clearTable(Config.class);
        initExcelData(Config.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    Config entity = (Config) params[1];
                    entity.setId(IdGen.nextId());
                    entity.setIsNewRecord(true);
                    configService.save(entity);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private ModuleService moduleService;

    /**
     * 系统模块表
     */
    public void initModule() throws Exception {
        clearTable(Module.class);
        initExcelData(Module.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    Module entity = (Module) params[1];
                    entity.setIsNewRecord(true);
                    moduleService.save(entity);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private DictTypeService dictTypeService;
    @Autowired
    private DictDataService dictDataService;

    /**
     * 系统字典、用户字典表
     */
    public void initDict() throws Exception {
        clearTable(DictType.class);
        initExcelData(DictType.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    DictType entity = (DictType) params[1];
                    entity.setId(IdGen.nextId());
                    entity.setIsNewRecord(true);
                    dictTypeService.save(entity);
                    return null;
                }
                return null;
            }
        });

        clearTable(DictData.class);
        initExcelData(DictData.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    DictData entity = (DictData) params[1];
                    entity.setIsNewRecord(true);
                    dictDataService.save(entity);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private RoleService roleService;

    /**
     * 角色表
     */
    public void initRole() throws Exception {
        clearTable(Role.class);
        clearTable(RoleMenu.class);
        clearTable(RoleDataScope.class);
        initExcelData(Role.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    Role entity = (Role) params[1];
                    entity.setIsNewRecord(true);
                    roleService.save(entity);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private MenuService menuService;
    @Autowired
    private RoleMenuDao roleMenuDao;

    /**
     * 菜单表
     */
    public void initMenu() throws Exception {
        clearTable(Menu.class);
        clearTable(RoleMenu.class);
        initExcelData(Menu.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    Menu entity = (Menu) params[1];
                    entity.setIsNewRecord(true);
                    menuService.save(entity);
                    RoleMenu rm = new RoleMenu();
                    rm.setMenuCode(entity.getMenuCode());
                    rm.setRoleCode(Role.CORP_ADMIN_ROLE_CODE);
                    roleMenuDao.insert(rm);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private UserService userService;

    /**
     * 用户表
     */
    public void initUser() throws Exception {
        clearTable(User.class);
        clearTable(UserRole.class);
        clearTable(UserDataScope.class);
        initExcelData(User.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    User entity = (User) params[1];
                    entity.setIsNewRecord(true);
                    userService.save(entity);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private OfficeService officeService;

    /**
     * 组织机构、部门表
     */
    public void initOffice() throws Exception {
        clearTable(Office.class);
        initExcelData(Office.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    Office entity = (Office) params[1];
                    entity.setIsNewRecord(true);
                    officeService.save(entity);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private CompanyService companyService;

    /**
     * 公司表
     */
    public void initCompany() throws Exception {
        clearTable(Company.class);
        clearTable(CompanyOffice.class);
        initExcelData(Company.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    Company entity = (Company) params[1];
                    entity.setIsNewRecord(true);
                    companyService.save(entity);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private PostService postService;

    /**
     * 岗位表
     */
    public void initPost() throws Exception {
        clearTable(Post.class);
        initExcelData(Post.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("save".equals(action)) {
                    Post entity = (Post) params[1];
                    entity.setIsNewRecord(true);
                    postService.save(entity);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private EmpUserService empUserService;

    /**
     * 员工、用户表
     */
    public void initEmpUser() throws Exception {
        clearTable(Employee.class);
        clearTable(EmployeePost.class);
        initExcelData(EmpUser.class, new MethodCallback() {
            @Override
            public Object execute(Object... params) {
                String action = (String) params[0];
                if ("set".equals(action)) {
                    EmpUser entity = (EmpUser) params[1];
                    String header = (String) params[2];
                    String val = (String) params[3];
                    if ("userRoleString".equals(header)) {
                        entity.setUserRoleString(val);
                        return true;
                    } else if ("employee.employeePosts".equals(header)) {
                        entity.getEmployee().setEmployeePosts(new String[]{val});
                        return true;
                    }
                } else if ("save".equals(action)) {
                    EmpUser entity = (EmpUser) params[1];
                    entity.setIsNewRecord(true);
                    empUserService.save(entity);
                    // 设置当前为管理员，否则无法保存用户角色关系
                    entity.setCurrentUser(new User(User.SUPER_ADMIN_CODE));
                    userService.saveAuth(entity);
                    return null;
                }
                return null;
            }
        });
    }

    @Autowired
    private JobDao jobDao; // 默认情况下job是关闭状态，需要注入jobDao

    /**
     * 初始化消息推送服务
     */
    public void initMsgPushJob() {
        JobEntity job = new JobEntity(MsgLocalPushTask.class.getSimpleName(), "SYSTEM");
        job.setDescription("消息推送服务 (实时推送)");
        job.setInvokeTarget("msgLocalPushTask.execute()");
        job.setCronExpression("0/3 * * * * ?");
        job.setConcurrent(Global.NO);
        job.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
        job.setStatus(JobEntity.STATUS_PAUSED);
        jobDao.insert(job);
        job = new JobEntity(MsgLocalMergePushTask.class.getSimpleName(), "SYSTEM");
        job.setDescription("消息推送服务 (延迟推送)");
        job.setInvokeTarget("msgLocalMergePushTask.execute()");
        job.setCronExpression("0 0/30 * * * ?");
        job.setConcurrent(Global.NO);
        job.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
        job.setStatus(JobEntity.STATUS_PAUSED);
        jobDao.insert(job);
    }

    @Autowired
    private GenTableService genTableService;

    /**
     * 代码生成测试数据
     */
    public void initGenTestData() throws Exception {
        GenTable genTable = new GenTable();
        genTable.setIsNewRecord(true);
        genTable.setTableName("test_data");
        genTable = genTableService.getFromDb(genTable);
        genTable.setIsNewRecord(true);
        genTable.setClassName("TestData");
        genTable.setFunctionAuthor("ThinkGem");
        genTable.setTplCategory("crud");
        genTable.setPackageName("com.jeesite.modules");
        genTable.setModuleName("test");
        genTable.setSubModuleName("");
        genTable.setFunctionName("测试数据");
        genTable.setFunctionNameSimple("数据");
        genTable.getOptionMap().put("isHaveDisableEnable", Global.YES);
        genTable.getOptionMap().put("isHaveDelete", Global.YES);
        genTable.getOptionMap().put("isFileUpload", Global.YES);
        genTable.getOptionMap().put("isImageUpload", Global.YES);
        initGenTableColumn(genTable);
        genTableService.save(genTable);
        // 子表
        GenTable genTableChild = new GenTable();
        genTableChild.setIsNewRecord(true);
        genTableChild.setTableName("test_data_child");
        genTableChild = genTableService.getFromDb(genTableChild);
        genTableChild.setIsNewRecord(true);
        genTableChild.setClassName("TestDataChild");
        genTableChild.setFunctionAuthor("ThinkGem");
        genTableChild.setTplCategory("crud");
        genTableChild.setPackageName("com.jeesite.modules");
        genTableChild.setModuleName("test");
        genTableChild.setSubModuleName("");
        genTableChild.setFunctionName("测试子表");
        genTableChild.setFunctionNameSimple("数据");
        genTableChild.setParentTableName("test_data");
        genTableChild.setParentTableFkName("test_data_id");
        initGenTableColumn(genTableChild);
        genTableService.save(genTableChild);
    }

    /**
     * 代码生成测试数据（列初始化）
     */
    private void initGenTableColumn(GenTable genTable) {
        for (GenTableColumn column : genTable.getColumnList()) {
            if ("test_input".equals(column.getColumnName())
                    || "test_textarea".equals(column.getColumnName())
                    || "test_select".equals(column.getColumnName())
                    || "test_select_multiple".equals(column.getColumnName())
                    || "test_checkbox".equals(column.getColumnName())
                    || "test_radio".equals(column.getColumnName())
                    || "test_date".equals(column.getColumnName())
                    || "test_datetime".equals(column.getColumnName())
                    ) {
                column.setShowType(StringUtils.substringAfter(
                        column.getColumnName(), "test_"));
                if ("test_input".equals(column.getColumnName())
                        ) {
                    column.setQueryType("LIKE");
                } else if ("test_textarea".equals(column.getColumnName())
                        ) {
                    column.setQueryType("LIKE");
                    column.getOptionMap().put("isNewLine", Global.YES);
                    column.getOptionMap().put("gridRowCol", "12/2/10");
                } else if ("test_select".equals(column.getColumnName())
                        || "test_select_multiple".equals(column.getColumnName())
                        || "test_radio".equals(column.getColumnName())
                        || "test_checkbox".equals(column.getColumnName())
                        ) {
                    column.getOptionMap().put("dictType", "sys_menu_type");
                    column.getOptionMap().put("dictName", "sys_menu_type");
                } else if ("test_date".equals(column.getColumnName())
                        || "test_datetime".equals(column.getColumnName())
                        ) {
                    column.setQueryType("BETWEEN");
                }
            } else if ("test_user_code".equals(column.getColumnName())) {
                column.setAttrType("com.jeesite.modules.sys.entity.User");
                column.setFullAttrName("testUser");
                column.setShowType("userselect");
            } else if ("test_office_code".equals(column.getColumnName())) {
                column.setAttrType("com.jeesite.modules.sys.entity.Office");
                column.setFullAttrName("testOffice");
                column.setShowType("officeselect");
            } else if ("test_area_code".equals(column.getColumnName())) {
                column.setFullAttrName("testAreaCode|testAreaName");
                column.setShowType("areaselect");
            } else if ("test_area_name".equals(column.getColumnName())) {
                column.setIsEdit(Global.NO);
                column.setIsQuery(Global.NO);
            } else if ("test_data_id".equals(column.getColumnName())) {
                column.setFullAttrName("testData");
            }
        }
    }

    /**
     * 代码生成树表测试数据
     */
    public void initGenTreeData() throws Exception {
        GenTable genTable = new GenTable();
        genTable.setIsNewRecord(true);
        genTable.setTableName("test_tree");
        genTable = genTableService.getFromDb(genTable);
        genTable.setIsNewRecord(true);
        genTable.setClassName("TestTree");
        genTable.setFunctionAuthor("ThinkGem");
        genTable.setTplCategory("treeGrid");
        genTable.setPackageName("com.jeesite.modules");
        genTable.setModuleName("test");
        genTable.setSubModuleName("");
        genTable.setFunctionName("测试树表");
        genTable.setFunctionNameSimple("数据");
        genTable.getOptionMap().put("isHaveDisableEnable", Global.YES);
        genTable.getOptionMap().put("isHaveDelete", Global.YES);
        genTable.getOptionMap().put("isFileUpload", Global.YES);
        genTable.getOptionMap().put("isImageUpload", Global.YES);
        genTable.getOptionMap().put("treeViewCode", "tree_code");
        genTable.getOptionMap().put("treeViewName", "tree_name");
        initGenTableColumn(genTable);
        genTableService.save(genTable);
    }
}
